#! -*- coding:utf-8 -*-

from uuid import uuid4

from common.account.db import account as account_db
from common.platform.common import db as third_db
from common.utils import exceptions as err
from common.utils.currency import convert_yuan_to_fen


class AbstractHandler(object):
    def get_platform_code(self):
        """
        返回当前游戏类型： PLATFORM_TYPE
        :return:
        """
        raise NotImplementedError()

    """
    所有接入的游戏实现该抽象类，实现方法中的抽象方法。
    注意： 所有金额参数和返回，单位都是分

    """

    def check_trans_existed(self, ref_id):
        """
        查询第三方交易是否存在

        :param ref_id:
        :return: True为存在
        """
        raise NotImplementedError()

    def calculate_accumulated_win_amount(self, user_id, start_time, end_time):
        """
        计算时间段用户累加派奖金额

        :param user_id: 用户id
        :param start_time: 开始时间
        :param end_time: 结束时间
        :return: int 累加派金额
        """
        raise NotImplementedError()

    def query_balance_and_frozen_status(self, user_id):
        """
        查询第三方游戏当前余额及是否有资金冻结
        :param user_id: 用户id
        :return: (balance: int, frozen_status: bool), balance: 当前余额, status: 是否有资金冻结，True为冻结状态
        """
        raise NotImplementedError()

    def available(self, *args, **kwargs):
        """
        当前第三方服务是否可用, 当不可用时，不能登入(login)第三方游戏, 但是可以登出(logout)
        :return:
        """
        raise NotImplementedError()

    def login(self, user_id, **callback_params):
        """
        进入游戏

        :param user_id: 用户id
        :param callback_params login_callback参数
        :return 返回 login_callback 结果
        """
        assert user_id > 0
        if not self.available(user_id, **callback_params):
            raise err.ServerError(u'游戏维护中，请稍后重试')

        ref_id = uuid4().hex
        account = account_db.get_account(user_id)
        frozen_amount = convert_yuan_to_fen(account.balance)
        if frozen_amount > 0:
            third_db.frozen_balance(user_id, self.get_platform_code(), frozen_amount, ref_id)

        try:
            return self.login_third(user_id, frozen_amount, ref_id, **callback_params)
        except:
            if not self.check_trans_existed(ref_id):
                third_db.reverse_not_existed_fronzen(user_id, ref_id)
            raise

    def login_third(self, user_id, amount, ref_id, **params):
        """
        集成第三方游戏进入逻辑，一般包括将用户资金换入第三方游戏账号
        :param user_id:
        :param amount
        :param ref_id
        :param params:
        """
        raise NotImplementedError()

    def logout(self, user_id, **callback_param):
        """
        退出游戏

        :param user_id:
        :param callback_param
        :return: (success: bool) 当前如果第三方游戏资金还在冻结中时，不能成功退出游戏，返回False
        """
        assert user_id > 0
        balance, frozen_status = self.query_balance_and_frozen_status(user_id)
        if frozen_status:
            return False

        ref_id = uuid4().hex
        # 先记录提现事务日志
        trans_log_id = third_db.add_withdraw_trans_log(user_id, self.get_platform_code(), balance, ref_id)
        if not self.logout_third(user_id, balance, ref_id, **callback_param):
            return False
        # 记入流水
        third_db.unfreeze_balance(user_id, self.get_platform_code(), balance, ref_id)
        # 删除提现事务日志
        third_db.delete_withdraw_trans_log(trans_log_id)
        return True

    def logout_third(self, user_id, amount, ref_id, **params):
        """
        集成第三方游戏退出逻辑，一般包括将第三方游戏资金换出到平台
        :param user_id:
        :param amount
        :param ref_id
        :return: bool 成功返回True
        """
        raise NotImplementedError()
